package de.doegel.common;

import greendroid.widget.ActionBarItem;
import greendroid.widget.ActionBarItem.Type;
import greendroid.widget.LoaderActionBarItem;

import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Pair;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;

import com.makeramen.segmented.SegmentedRadioGroup;
import com.markupartist.android.widget.PullToRefreshListView;
import com.markupartist.android.widget.PullToRefreshListView.OnRefreshListener;

import de.doegel.common.model.AbstractMessage;
import de.doegel.common.model.IncomingMessage;
import de.doegel.common.model.OutgoingMessage;
import de.doegel.common.ormlite.OrmLiteGDActivity;
import de.doegel.common.util.ImageDownloader;
import de.doegel.common.util.TextAndProgressBarUtils;
import de.doegel.common.util.Utils;

public class MessagesActivity<H extends AbstractDatabaseHelper> extends OrmLiteGDActivity<H> {
	private ImageDownloader imageDownloader = new ImageDownloader();

	class MessagesAdapter extends BaseAdapter {
		public String footerMessage = null;
		public boolean footerClickable = false;
		public boolean footerProgressBarVisible = true;

		List<AbstractMessage> all;

		public MessagesAdapter(List<AbstractMessage> all) {
			this.all = all;
		}

		public int getCount() {
			return all.size();
		}

		public AbstractMessage getItem(int position) {
			return all.get(position);
		}

		public long getItemId(int position) {
			return position;
		}

		public final View getView(int position, View convertView, ViewGroup parent) {
			View res = convertView;
			if (res == null)
				res = getLayoutInflater().inflate(R.layout.message_item, null);

			TextView nameTextView = (TextView) res.findViewById(R.id.contact_name);
			ImageView contactImageView = (ImageView) res.findViewById(R.id.contact_image);
			TextView dateTextView = (TextView) res.findViewById(R.id.message_date);
			TextView subjectTextView = (TextView) res.findViewById(R.id.message_subject);

			AbstractMessage message = getItem(position);

			nameTextView.setText(message.fromtoName);
			if (message instanceof IncomingMessage) {
				nameTextView.setTextColor(message.read ? getResources().getColor(R.color.text_color) : getResources().getColor(R.color.unread_message_text_color));
			} else {
				nameTextView.setTextColor(getResources().getColor(R.color.text_color));
			}
			dateTextView.setText(Utils.parseAndFormatDate(message.date, IDoegelConstants.MESSAGE_DATE_PARSER_FORMAT, IDoegelConstants.LIST_DATE_FORMATTER_FORMAT));
			subjectTextView.setText(message.subject);
			contactImageView.setImageResource(R.drawable.empty_contact_image);
			imageDownloader.download(message.fromtoImageURL, contactImageView);

			return res;
		}

		public List<AbstractMessage> getMessages() {
			return all;
		}
	}

	private static final int MESSAGE_DETAILS_REQUEST = 1;
	private static final int MESSAGE_COMPOSE_REQUEST = 2;

	private LoaderActionBarItem refreshItem = null;
	private MessagesAdapter inboxAdapter;
	private MessagesAdapter outboxAdapter;
	private PullToRefreshListView inboxListview;
	private PullToRefreshListView outboxListview;
	private SegmentedRadioGroup radiogroup;

	private Comparator<AbstractMessage> comparator = new Comparator<AbstractMessage>() {
		@Override
		public int compare(AbstractMessage m1, AbstractMessage m2) {
			return m2.id - m1.id;
		}
	};

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setActionBarContentView(R.layout.messages);
		setTitle(R.string.messages_activity_title);
		Bundle bundle = getIntent().getExtras();
		if(bundle!=null){
			startActivityForResult(Utils.createMessageIntent(MessagesActivity.this, true, bundle.getInt("id")), MESSAGE_DETAILS_REQUEST);
		}
		refreshItem = (LoaderActionBarItem) addActionBarItem(Type.Refresh, R.id.action_bar_refresh);
		addActionBarItem(Type.Compose, R.id.action_bar_compose);

		inboxListview = (PullToRefreshListView) findViewById(R.id.inbox_list);
		inboxListview.setOnRefreshListener(new OnRefreshListener() {
			public void onRefresh() {
				refreshMessages();
			}
		});
		inboxListview.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
			public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
				menu.add(0, CONTEXT_MENU_DELETE, 0, R.string.delete_message_context_menu);
			}
		});

		inboxListview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
				if (position >= 1) {
					AbstractMessage message = inboxAdapter.getItem(position - 1);
					startActivityForResult(Utils.createMessageIntent(MessagesActivity.this, true, message.id), MESSAGE_DETAILS_REQUEST);
				}
			}
		});

		outboxListview = (PullToRefreshListView) findViewById(R.id.outbox_list);
		outboxListview.setOnRefreshListener(new OnRefreshListener() {
			public void onRefresh() {
				refreshMessages();
			}
		});
		outboxListview.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
			public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
				menu.add(0, CONTEXT_MENU_DELETE, 0, R.string.delete_message_context_menu);
			}
		});

		outboxListview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
				if (position >= 1) {
					AbstractMessage message = outboxAdapter.getItem(position - 1);
					startActivityForResult(Utils.createMessageIntent(MessagesActivity.this, false, message.id), MESSAGE_DETAILS_REQUEST);
				}
			}
		});

		createFooter(inboxListview);
		createFooter(outboxListview);

		inboxAdapter = new MessagesAdapter(new Vector<AbstractMessage>());
		inboxListview.setAdapter(inboxAdapter);
		outboxAdapter = new MessagesAdapter(new Vector<AbstractMessage>());
		outboxListview.setAdapter(outboxAdapter);

		radiogroup = (SegmentedRadioGroup) findViewById(R.id.mailbox);
		radiogroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			public void onCheckedChanged(RadioGroup group, int checkedId) {
				changeMessagesList(checkedId == R.id.inbox);
			}
		});

		((ProgressBar) inboxListview.findViewById(R.id.pull_to_refresh_progress)).setIndeterminateDrawable(getResources().getDrawable(R.drawable.progressbar_animation));
		((ProgressBar) outboxListview.findViewById(R.id.pull_to_refresh_progress)).setIndeterminateDrawable(getResources().getDrawable(R.drawable.progressbar_animation));

		new FetchMessagesFromDBTask().execute();

		Utils.setUnreadMessageCount(this, 0);
	}

	public void onNewIntent(Intent intent) {
		super.onNewIntent(intent);

		Utils.setUnreadMessageCount(this, 0);
		new FetchIncomingMessagesFromDBTask().execute();
	}

	@Override
	public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
		if (item.getItemId() == R.id.action_bar_refresh) {
			refreshMessages();
			return true;
		} else if (item.getItemId() == R.id.action_bar_compose) {
			startActivityForResult(Utils.createComposeMessageIntent(this), MESSAGE_COMPOSE_REQUEST);
			return true;
		} else {
			return super.onHandleActionBarItemClick(item, position);
		}
	}

	private void createFooter(ListView listview) {
		View textandprogressbar = getLayoutInflater().inflate(R.layout.text_and_progressbar, listview, false);
		listview.addFooterView(textandprogressbar, null, false);
		TextAndProgressBarUtils.initializeTextAndProgressBar(listview, textandprogressbar);
	}

	@SuppressWarnings("unchecked")
	public void onTextAndProgressBarClick(View view) {
		PullToRefreshListView listview = radiogroup.getCheckedRadioButtonId() == R.id.inbox ? inboxListview : outboxListview;
		TextAndProgressBarUtils.configureTextAndProgressBar(listview, null, false, true);
		TextAndProgressBarUtils.showTextAndProgressBar(listview);
		new FetchMessagesTask().execute(new Pair<Boolean, Boolean>(radiogroup.getCheckedRadioButtonId() == R.id.inbox, false));
	}

	private void changeMessagesList(boolean inbox) {
		if (inbox) {
			inboxListview.setVisibility(View.VISIBLE);
			outboxListview.setVisibility(View.GONE);
		} else {
			inboxListview.setVisibility(View.GONE);
			outboxListview.setVisibility(View.VISIBLE);
		}
	}

	@SuppressWarnings("unchecked")
	public void refreshMessages() {
		new FetchMessagesTask().execute(new Pair<Boolean, Boolean>(radiogroup.getCheckedRadioButtonId() == R.id.inbox, true));
	}

	public void deleteMessage(int position) {
		boolean inbox = radiogroup.getCheckedRadioButtonId() == R.id.inbox;
		MessagesAdapter adapter = inbox ? inboxAdapter : outboxAdapter;
		if (position < 1)
			return;
		final AbstractMessage message = adapter.getItem(position - 1);

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(getString(R.string.message_remove_are_you_sure)).setCancelable(true).setPositiveButton(getString(R.string.dialog_yes), new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
				if (message != null) {
					new DeleteMessageTask().execute(message);
				}
			}
		}).setNegativeButton(getString(R.string.dialog_no), new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		builder.setTitle(R.string.dialog_warning);
		builder.create().show();
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == MESSAGE_DETAILS_REQUEST) {
			boolean inbox = radiogroup.getCheckedRadioButtonId() == R.id.inbox;
			MessagesAdapter adapter = inbox ? inboxAdapter : outboxAdapter;
			PullToRefreshListView listview = inbox ? inboxListview : outboxListview;

			if (data != null && data.getExtras() != null && data.getExtras().containsKey(IDoegelConstants.MESSAGE_ID_EXTRA)) {
				int messageId = data.getExtras().getInt(IDoegelConstants.MESSAGE_ID_EXTRA);
				AbstractMessage message = null;
				for (int i = 0; i < adapter.getMessages().size(); i++) {
					if (adapter.getMessages().get(i).id == messageId) {
						message = adapter.getMessages().get(i);
						break;
					}
				}
				if (resultCode == IDoegelConstants.MESSAGE_DELETED_RESULT) {
					adapter.getMessages().remove(message);
				} else {
					message.read = true;
				}

				listview.invalidateViews();
			}
		}
	}

	private class FetchMessagesFromDBTask extends AsyncTask<Void, Void, Void> {
		List<IncomingMessage> incomingMessages;
		List<OutgoingMessage> outgoingMessages;

		@Override
		protected void onPreExecute() {

		}

		@Override
		protected Void doInBackground(Void... params) {
			try {
				incomingMessages = getHelper().getInboxDao().queryForAll();
				Collections.sort(incomingMessages, comparator);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				outgoingMessages = getHelper().getOutboxDao().queryForAll();
				Collections.sort(outgoingMessages, comparator);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			inboxAdapter.getMessages().clear();
			outboxAdapter.getMessages().clear();
			if (incomingMessages != null) {
				inboxAdapter.getMessages().addAll(incomingMessages);
			}
			if (outgoingMessages != null) {
				outboxAdapter.getMessages().addAll(outgoingMessages);
			}
			
			inboxListview.onRefreshComplete();
			outboxListview.onRefreshComplete();
			
			Log.e("AAA", inboxListview.getFirstVisiblePosition() + " " + inboxListview.getLastVisiblePosition() + " " + inboxListview.getAdapter().getCount());

			if (inboxAdapter.getMessages().size() == 0) {
				TextAndProgressBarUtils.configureTextAndProgressBar(inboxListview, getString(R.string.message_nothing), false, false);
			} else if (inboxAdapter.getMessages().size() >= 8){
				TextAndProgressBarUtils.configureTextAndProgressBar(inboxListview, getString(R.string.message_old), false, false);
			} else {
				TextAndProgressBarUtils.configureTextAndProgressBar(inboxListview, "", false, false);
			}
			if (outboxAdapter.getMessages().size() == 0) {
				TextAndProgressBarUtils.configureTextAndProgressBar(outboxListview, getString(R.string.message_nothing), false, false);
			} else if (outboxAdapter.getMessages().size() >= 8){
				TextAndProgressBarUtils.configureTextAndProgressBar(outboxListview, getString(R.string.message_old), false, false);
			} else {
				TextAndProgressBarUtils.configureTextAndProgressBar(outboxListview, "", false, false);
			}
			
			super.onPostExecute(result);
		}
	}

	private class FetchIncomingMessagesFromDBTask extends AsyncTask<Void, Void, List<IncomingMessage>> {
		@Override
		protected void onPreExecute() {

		}

		@Override
		protected List<IncomingMessage> doInBackground(Void... params) {
			try {
				List<IncomingMessage> messages = getHelper().getInboxDao().queryForAll();
				Collections.sort(messages, comparator);
				return messages;
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(List<IncomingMessage> result) {
			if (result != null && result.size() > 0) {
				inboxAdapter.getMessages().clear();
				inboxAdapter.getMessages().addAll(result);
				inboxListview.invalidateViews();
				if (radiogroup.getCheckedRadioButtonId() == R.id.outbox) {
					radiogroup.check(R.id.inbox);
				}
			}

			super.onPostExecute(result);
		}
	}

	private class FetchMessagesTask extends AsyncTask<Pair<Boolean, Boolean>, Void, List<AbstractMessage>> {
		private boolean inbox = true;
		private boolean newRefresh = true;
		private int resultSize = 0;

		@Override
		protected List<AbstractMessage> doInBackground(Pair<Boolean, Boolean>... params) {
			inbox = params[0].first;
			newRefresh = params[0].second;
			MessagesAdapter adapter = inbox ? inboxAdapter : outboxAdapter;
			List<AbstractMessage> result = ((DoegelApplication) getApplication()).getHttpConnector().fetchMessages(MessagesActivity.this, inbox, newRefresh ? 0 : adapter.getMessages().size());
			if (result == null)
				return null;

			resultSize = result.size();

			List<AbstractMessage> messages = new Vector<AbstractMessage>();
			try {
				if (newRefresh) {
					if (inbox) {
						getHelper().getInboxDao().delete(getHelper().getInboxDao().queryForAll());
					} else {
						getHelper().getOutboxDao().delete(getHelper().getOutboxDao().queryForAll());
					}
				}
				for (int i = 0; i < result.size(); i++) {
					if (inbox) {
						getHelper().getInboxDao().create((IncomingMessage) result.get(i));
					} else {
						getHelper().getOutboxDao().create((OutgoingMessage) result.get(i));
					}
				}
				if (inbox) {
					messages.addAll(getHelper().getInboxDao().queryForAll());
				} else {
					messages.addAll(getHelper().getOutboxDao().queryForAll());
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			Collections.sort(messages, comparator);
			return messages;
		}

		@Override
		protected void onPostExecute(List<AbstractMessage> messages) {
			PullToRefreshListView listview = inbox ? inboxListview : outboxListview;
			if (messages != null) {
				MessagesAdapter adapter = inbox ? inboxAdapter : outboxAdapter;
				adapter.getMessages().clear();
				adapter.getMessages().addAll(messages);
				if (resultSize < 25) {
					TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.message_nomore), false, false);
				} else {
					TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.message_more), true, false);
				}
			} else {
				TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.network_problem), false, false);
			}

			// Call onRefreshComplete when the list has been refreshed.
			if (newRefresh) {
				listview.onRefreshComplete();
				// listview.setLastUpdated("10 days ago");
			} else {
				listview.invalidateViews();
			}

			refreshItem.setLoading(false);

			super.onPostExecute(messages);
		}
	}

	private class DeleteMessageTask extends AsyncTask<AbstractMessage, Void, Boolean> {
		ProgressDialog dialog;
		AbstractMessage message;

		@Override
		protected void onPreExecute() {
			dialog = new ProgressDialog(MessagesActivity.this);
			dialog.setMessage(getString(R.string.message_removing));
			dialog.setIndeterminate(true);
			dialog.setCancelable(false);
			dialog.show();
		}

		@Override
		protected Boolean doInBackground(AbstractMessage... params) {
			message = params[0];
			return ((DoegelApplication) getApplication()).getHttpConnector().deleteMessage(MessagesActivity.this, message.id);
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if (result) {
				try {
					if (message instanceof IncomingMessage) {
						getHelper().getInboxDao().delete((IncomingMessage) message);
					} else {
						getHelper().getOutboxDao().delete((OutgoingMessage) message);
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
				if (message instanceof IncomingMessage) {
					inboxAdapter.getMessages().remove(message);
					inboxListview.invalidateViews();
				} else {
					outboxAdapter.getMessages().remove(message);
					outboxListview.invalidateViews();
				}
				dialog.dismiss();
			} else {
				dialog.dismiss();
				Utils.showAlertDialog(MessagesActivity.this, getString(R.string.message_removing_error_title), getString(R.string.message_removing_error));
			}

			super.onPostExecute(result);
		}
	}

	private static final int CONTEXT_MENU_HOME = 0;
	private static final int CONTEXT_MENU_SETTINGS = 1;
	private static final int CONTEXT_MENU_REFRESH = 2;
	private static final int CONTEXT_MENU_COMPOSE = 3;

	private static final int CONTEXT_MENU_DELETE = 4;

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, CONTEXT_MENU_HOME, 0, R.string.home_context_menu);
		menu.add(0, CONTEXT_MENU_SETTINGS, 0, R.string.settings_context_menu);
		menu.add(0, CONTEXT_MENU_REFRESH, 0, R.string.refresh_context_menu);
		menu.add(0, CONTEXT_MENU_COMPOSE, 0, R.string.compose_context_menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case CONTEXT_MENU_HOME:
			startActivity(Utils.createHomeIntent(this));
			return true;
		case CONTEXT_MENU_SETTINGS:
			startActivity(Utils.createSettingsIntent(this));
			finish();
			return true;
		case CONTEXT_MENU_REFRESH:
			refreshItem.setLoading(true);
			refreshMessages();
			return true;
		case CONTEXT_MENU_COMPOSE:
			startActivityForResult(Utils.createComposeMessageIntent(this), MESSAGE_COMPOSE_REQUEST);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case CONTEXT_MENU_DELETE:
			AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
			deleteMessage(menuInfo.position);
			break;
		default:
			return super.onContextItemSelected(item);
		}
		return true;
	}
}